import com.andong.*;

import java.io.File;
import java.io.InputStream;
import java.util.*;

public class CompareTablesMain {

	public static final String DB_REPORT = "DBReport";
	public static final String DB_COMPARE = "DBCompare";

	public static void main(String[] args) {
		printDBConInfo();
		String input = "z";
		int firstSn = 0;
		int secondSn = 0;
		String tableReportPath = "CompareReport" + File.separator + DB_REPORT; // 扫描报告目录路径
		String tableComparePath = "CompareReport" + File.separator + DB_COMPARE; // 比对结果目录路径
		Scanner sc = new Scanner(System.in);
		while (!input.equalsIgnoreCase("Q")) {
			int tableCompareReportNumber = getTableCompareReportNumber(tableReportPath);
			System.out.print("目前存在" + tableCompareReportNumber + "个状态报告.");
			if (1 >= tableCompareReportNumber) {
				System.out.println("是否进行一次新的扫描?");
				System.out.print("输入'Y'进行扫描,'N'不扫描,'Q'退出:");
				input = sc.nextLine();
				if (input.equalsIgnoreCase("Y")) {
					System.out.println("生成新的扫描报告: " + newDBReportScan(tableReportPath));
				} else if (input.equalsIgnoreCase("N")) {
					printMainMenu();
				}
			} else {
				printMainMenu();
				input = sc.nextLine();
				if (input.equals("1")) {
					System.out.println("生成新的扫描报告: " + newDBReportScan(tableReportPath));
				}
				if (input.equals("2")) {
					String[] fileNameList = FileUtil.getFileNameList(tableReportPath, ".txt");
					int secondDefault = fileNameList.length;
					if (secondDefault > 0) {
						int firstDefault = secondDefault - 1;
						System.out.println("请输入第一个比对文件的序号(小于等于" + tableCompareReportNumber + "):");
						System.out.print("直接回车则为 " + firstDefault + " : ");

						if (sc.hasNextLine()) {
							String firstInput = sc.nextLine();
							firstSn = ("".equals(firstInput)) ? firstDefault : Integer.parseInt(firstInput);
						}
						if(firstSn == 0){
							System.out.println("序号不在合理范围");
							continue;
						}
						System.out.println("请输入第二个比对文件的序号(小于等于" + tableCompareReportNumber + "):");
						System.out.print("直接回车则为 " + secondDefault + " : ");

						if (sc.hasNextLine()) {
							String secondInput = sc.nextLine();
							secondSn = ("".equals(secondInput)) ? secondDefault : Integer.parseInt(secondInput);
						}
						if(secondSn == 0){
							System.out.println("序号不在合理范围");
							continue;
						}

						String tcr = newDBCompareResult(tableReportPath, tableComparePath, firstSn, secondSn);
						if(tcr.length() > 0){
							System.out.println("生成新的比对报告: ");
							System.out.println("TableName\tOrigin\tNew");
							System.out.println(tcr);
						}
					}
				}
				if (input.equals("3")) {
					listTableReport(tableReportPath);
				}
			}
			System.out.println("/*************************/");
		}

	}

	/**
	 * list current table comparing report files
	 *
	 * @param tableReportPath folder of table comparing report files
	 */
	private static int listTableReport(String tableReportPath) {
		System.out.println("现有报告文件列表: ");
		String[] fileNameList = FileUtil.getFileNameList(tableReportPath, ".txt");
		if (null != fileNameList && 0 < fileNameList.length) {
			int i = 1;
			for (String fileName : fileNameList) {
				System.out.println((i++) + ": " + fileName);
			}
		}
		return fileNameList.length;
	}

	/**
	 * 显示主菜单
	 */
	private static void printMainMenu() {
		System.out.println("请选择功能:");
		System.out.println("1.进行一次新的扫描");
		System.out.println("2.比对现有报告");
		System.out.println("3.查看现有报告文件列表");
		System.out.println("Q.退出");
		System.out.print("请输入:");
	}

	/**
	 * 打印数据库连接信息
	 */
	private static void printDBConInfo() {
		String serverName = null;
		String userName = null;
		String password = null;
		String dataBaseName = null;
		int port = 0;
		Properties properties = new Properties();
		InputStream inputStream = CompareTablesMain.class.getResourceAsStream("config/DB.properties");
		try {
			properties.load(inputStream);
			serverName = properties.getProperty("serverName");
			port = Integer.parseInt(properties.getProperty("port"));
			dataBaseName = properties.getProperty("dataBaseName");
			userName = properties.getProperty("userName");
			password = properties.getProperty("password");
			System.out.println("Database connection info: ");
			System.out.println("Server name: " + serverName);
			System.out.println("Service port: " + port);
			System.out.println("Database name: " + dataBaseName);
			System.out.println("User name: " + userName);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 生成新的表比对结果
	 *
	 * @param tableReportPath  扫描结果目录路径
	 * @param tableComparePath 比对结果目录路径
	 * @param firstIndex       第1个比对文件的序号(从1开始)
	 * @param secondIndex      第2个比对文件的序号(从1开始)
	 * @return 成功则返回对比结果字符串, 失败返回空串
	 */
	private static String newTableCompareResult(String tableReportPath, String tableComparePath, int firstIndex, int secondIndex) {
		String[] fileNameList = FileUtil.getFileNameList(tableReportPath, ".txt");
		if (firstIndex > fileNameList.length) {
			System.out.println("第1个比对文件的序号 '" + (firstIndex) + "',超出了文件总数 '" + fileNameList.length + "'");
			return "";
		}
		if (secondIndex > fileNameList.length) {
			System.out.println("第2个比对文件的序号 '" + (firstIndex + 1) + "',超出了文件总数 '" + fileNameList.length + "'");
			return "";
		}
		TreeMap<String, Integer> mapFirstReport = readTableReport(tableReportPath, fileNameList[firstIndex - 1]);
		ArrayList<String> txtList = FileUtil.readTxtLines(tableReportPath + File.separator + fileNameList[firstIndex - 1]);

		TreeMap<String, Integer> mapSecondReport = readTableReport(tableReportPath, fileNameList[secondIndex - 1]);
		List<OneLineCompareResult> oneLineCompareResultList = compareTableReport(mapFirstReport, mapSecondReport);
		List<OneLineCompareResult> tableChangedList = new ArrayList<>();
		StringBuffer sbTcr = new StringBuffer();
		for (OneLineCompareResult oneLineCompareResult : oneLineCompareResultList) {
			sbTcr.append(oneLineCompareResult.getTableName() + "\t"
					+ oneLineCompareResult.getFirstCount() + "\t" + oneLineCompareResult.getSecondCount() + "\t"
					+ (oneLineCompareResult.getSecondCount() - oneLineCompareResult.getFirstCount()) + "\n");
			if (oneLineCompareResult.getFirstCount() != oneLineCompareResult.getSecondCount()) {
				// Write down changed table
				OneLineCompareResult tableChanged = new OneLineCompareResult();
				tableChanged.setTableName(oneLineCompareResult.getTableName());
				tableChanged.setFirstCount(oneLineCompareResult.getFirstCount());
				tableChanged.setSecondCount(oneLineCompareResult.getSecondCount());
				tableChangedList.add(tableChanged);
			}
		}
		if (sbTcr.charAt(sbTcr.length() - 1) == '\n') {
			sbTcr.append("*****Changed table*****\n");
			for (OneLineCompareResult tableChanged : tableChangedList) {
				sbTcr.append(tableChanged.getTableName() + "\t"
						+ tableChanged.getFirstCount() + "\t" + tableChanged.getSecondCount() + "\t"
						+ (tableChanged.getSecondCount() - tableChanged.getFirstCount()) + "\n");
			}
		}
		if (sbTcr.charAt(sbTcr.length() - 1) == '\n') {
			sbTcr.deleteCharAt(sbTcr.length() - 1);
		}
		FileUtil.writeTxt(tableComparePath, sbTcr.toString());
		return sbTcr.toString();
	}
	/**
	 * 生成新的表比对结果
	 *
	 * @param tableReportPath  扫描结果目录路径
	 * @param tableComparePath 比对结果目录路径
	 * @param firstIndex       第1个比对文件的序号(从1开始)
	 * @param secondIndex      第2个比对文件的序号(从1开始)
	 * @return 成功则返回对比结果字符串, 失败返回空串
	 */
	private static String newDBCompareResult(String tableReportPath, String tableComparePath, int firstIndex, int secondIndex) {
		String[] fileNameList = FileUtil.getFileNameList(tableReportPath, ".txt");
		if (firstIndex > fileNameList.length) {
			System.out.println("第1个比对文件的序号 '" + (firstIndex) + "',超出了文件总数 '" + fileNameList.length + "'");
			return "";
		}
		if (secondIndex > fileNameList.length) {
			System.out.println("第2个比对文件的序号 '" + (firstIndex + 1) + "',超出了文件总数 '" + fileNameList.length + "'");
			return "";
		}
		ArrayList<String> txtList = FileUtil.readTxtLines(tableReportPath + File.separator + fileNameList[firstIndex - 1]);
		DBReport firstDBReport = new DBReport(JdbcUtil.TABLE_TITLE, JdbcUtil.TABLE_END,
			JdbcUtil.VIEW_TITLE, JdbcUtil.VIEW_END, txtList);
		txtList = FileUtil.readTxtLines(tableReportPath + File.separator + fileNameList[secondIndex - 1]);
		DBReport secondDBReport = new DBReport(JdbcUtil.TABLE_TITLE, JdbcUtil.TABLE_END,
			JdbcUtil.VIEW_TITLE, JdbcUtil.VIEW_END, txtList);
		DBCompareMan dbCompareMan = new DBCompareMan(firstDBReport, secondDBReport);
		String strDBCompareResult = dbCompareMan.compare();

		System.out.println(strDBCompareResult);


		FileUtil.writeTxt(tableComparePath, strDBCompareResult);
		return strDBCompareResult;
	}

	/**
	 * compare table report, return List(tablename, first count, second count)
	 * @param mapFirstReport  first table report
	 * @param mapSecondReport second table report
	 * @return compare result
	 */
	private static List<OneLineCompareResult> compareTableReport(TreeMap<String, Integer> mapFirstReport, TreeMap<String, Integer> mapSecondReport) {
		if (mapFirstReport.size() != mapSecondReport.size()) {
			return null;
		}
		Iterator<Map.Entry<String, Integer>> iterator = mapFirstReport.entrySet().iterator();
		List<OneLineCompareResult> compareResultArrayList = new ArrayList<>();
		while (iterator.hasNext()) {
		OneLineCompareResult oneLineCompareResult = new OneLineCompareResult();
			Map.Entry<String, Integer> entry = iterator.next();
			oneLineCompareResult.setTableName(entry.getKey());
			oneLineCompareResult.setFirstCount(entry.getValue());
			oneLineCompareResult.setSecondCount(mapSecondReport.get(entry.getKey()));
			compareResultArrayList.add(oneLineCompareResult);
		}
		return compareResultArrayList;
	}

	/**
	 * 读取扫描结果文件,返回结果
	 * @param reportPath 扫描结果路径
	 * @param tableReportFileName
	 * @return 返回表名和记录数组成的HashMap
	 */
	private static TreeMap<String, Integer> readTableReport(String reportPath, String tableReportFileName) {
		TreeMap<String, Integer> mapReport = new TreeMap<>((o1, o2) -> {
			if(o1 == null || o2 == null)  return 0;
			return o1.toUpperCase().compareTo(o2.toUpperCase());
		});
		ArrayList<String> txtList = FileUtil.readTxtLines(reportPath + File.separator + tableReportFileName);
		for (String txtLine : txtList) {
			String[] oneLineTxts = txtLine.split("\\t"); // 用tab分割表名和记录数
			mapReport.put(oneLineTxts[0], Integer.parseInt(oneLineTxts[1]));
		}
		return mapReport;
	}

	/**
	 * 进行一次新的DB扫描
	 * 包括表和视图
	 * @param tableReportPath 扫描结果目录路径
	 */
	private static String newDBReportScan(String tableReportPath) {
		String serverName = null;
		String userName = null;
		String password = null;
		String dataBaseName = null;
		int port = 0;
		Properties properties = new Properties();
		InputStream inputStream = CompareTablesMain.class.getResourceAsStream("config/DB.properties");
		try {
			properties.load(inputStream);
			serverName = properties.getProperty("serverName");
			port = Integer.parseInt(properties.getProperty("port"));
			dataBaseName = properties.getProperty("dataBaseName");
			userName = properties.getProperty("userName");
			password = properties.getProperty("password");
		} catch (Exception e) {
			e.printStackTrace();
		}
		StringBuffer textContent = new StringBuffer();
		JdbcUtil jdbcUtil = new JdbcUtil(serverName, dataBaseName, port, userName, password);
		textContent.append("/* Server:   " + serverName + " */\n");
		textContent.append("/* Port:     " + port + " */\n");
		textContent.append("/* Database: " + dataBaseName + " */\n");
		textContent.append("/* Username: " + userName + " */\n");
		textContent.append(jdbcUtil.getTableListString());
		textContent.append(jdbcUtil.getViewListString());
		System.out.println("扫描报告：" + "\n" + textContent);

		if (textContent.length() > 0 && textContent.charAt(textContent.length() - 1) == '\n') {
			return FileUtil.writeTxt(tableReportPath, textContent.substring(0, textContent.length() - 1));
		}
		return "";
	}

	/**
	 * 取对比报告数量
	 * @return
	 */
	private static int getTableCompareReportNumber(String tableReportPath) {
		String[] fileNameList = FileUtil.getFileNameList(tableReportPath, ".txt");
		if (null != fileNameList && 0 < fileNameList.length) {
			return fileNameList.length;
		}
		return 0;
	}


}

